package com.zishuimuyu.job.download;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpConfig;
import cn.hutool.extra.ftp.FtpMode;
import cn.hutool.extra.ssh.Sftp;
import cn.hutool.setting.Setting;
import cn.hutool.setting.SettingUtil;
import com.zishuimuyu.utills.SaveRecordsUtil;
import lombok.extern.slf4j.Slf4j;
import org.ini4j.Ini;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 本任务只用来下载并上传文件,且上传发生在下载之后,避免将未完全下载成功的文件上传,保证文件完整性
 *
 * @author：GJH
 * @date
 * @company：北京木联能软件股份有限公司
 */
@Slf4j
public class DownloadAndUploadFileJob {
    private static Setting downloadSetting = SettingUtil.getFirstFound("config/downloadFile.setting");
    private static String localPath = "";
    private static String localBackPath = "";
    private static String countFilePath = "";
    private static String remotePath = "";
    private static String filePrefix = "";
    private static String fileExtension = "";
    private static String delete = "";

    //静态代码块会在依赖注入后自动执行,并优先执行 下载
    static {
        localPath = downloadSetting.getStr("localPath");
        localBackPath = downloadSetting.getStr("localBackPath");
        countFilePath =downloadSetting.getStr("countFilePath");
        remotePath = downloadSetting.getStr("remotePath");
        filePrefix = downloadSetting.getStr("filePrefix");
        fileExtension = downloadSetting.getStr("fileExtension");
        delete = downloadSetting.getStr("delete");
    }

    /**
     * 将要执行的方法所在的类交个spring容器扫描(@Component),并且在要执行的方法上添加@PostConstruct注解或者静态代码块执行**
     *
     * @Postcontruct’在依赖注入完成后自动调用
     */
    public void download() {
        if ("false".equals(downloadSetting.getStr("downloadJobEnable"))) {
            //未启用上传任务,返回
            // Thread t = Thread.currentThread();
            // String name = t.getName();
            // log.info(DateUtil.now() + name);
            // log.info("下载任务未启用");
            return;
        }
        log.info("定时任务下载任务启用：{}->> {}", remotePath, localBackPath);
        String protocol = downloadSetting.getStr("protocol");
        int defaultPort = "sftp".equalsIgnoreCase(protocol) ? 22 : 21;
        String host = downloadSetting.getStr("host");
        String charset = downloadSetting.getStr("Charset");
        Integer port = downloadSetting.getInt("port",defaultPort);
        String userName = downloadSetting.getStr("userName");
        String passWord = downloadSetting.getStr("passWord");
        Long sessionConnectTimeout = downloadSetting.getLong("sessionConnectTimeout",2000L);
        Long channelConnectedTimeout = downloadSetting.getLong("channelConnectedTimeout",2000L);
        FtpConfig config = new FtpConfig(host, port, userName, passWord, CharsetUtil.charset(charset));
        config.setConnectionTimeout(sessionConnectTimeout);
        config.setSoTimeout(channelConnectedTimeout);
        FileUtil.mkdir(localPath);
        FileUtil.mkdir(localBackPath);
        FileUtil.mkdir(countFilePath);
        List<String> downloadedList = new ArrayList<>();

        try {
            if ("sftp".equalsIgnoreCase(protocol)) {
                downloadedList = sftpDownload(config);
            }
            if ("ftp".equalsIgnoreCase(protocol)) {
                downloadedList = ftpDownload(config);
            }
            String iniFileName = "downloadedFileNames.ini";
            File file = FileUtil.touch(countFilePath, iniFileName);
            //保存下载记录
            SaveRecordsUtil.saveDownloadLog(file, downloadedList);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    /**
     * sftp下载
     *
     * @param config
     * @return java.util.List<java.lang.String>
     */
    public static List<String> sftpDownload(FtpConfig config) throws IOException {
        Sftp sftp = new Sftp(config);
        List<String> fileNames = sftp.ls(remotePath);
        if (!"*".equals(filePrefix)) {
            //根据filePrefix 前缀过滤
            fileNames = fileNames.stream().filter(fileName -> fileName.startsWith(filePrefix)).collect(Collectors.toList());
        }
        if (!"*".equals(fileExtension)) {
            //根据fileExtension 后缀过滤
            fileNames = fileNames.stream().filter(fileName -> fileName.endsWith(fileExtension)).collect(Collectors.toList());
        }
        //避免重复下载（远端服务器文件未及时删除，会重复下载），先查看已经下载过的文件
        File file = FileUtil.touch(countFilePath, "downloadedFileNames" + ".ini");
        Ini ini = new Ini(file);
        Set<String> downloadedFileNames = ini.get("downloadedFileNames").keySet();
        //筛选出没有下载的文件名
        fileNames = fileNames.stream().filter(fileName -> !downloadedFileNames.contains(fileName)).collect(Collectors.toList());
        ArrayList<String> downloadedList = new ArrayList<>();
        for (String fileName : fileNames) {
            //先下载到备份补录
            sftp.download(remotePath + "/" + fileName, FileUtil.file(localBackPath, fileName));
            //再从备份复制到本地目录
            FileUtil.copy(FileUtil.file(localBackPath, fileName), FileUtil.file(localPath, fileName), true);
            downloadedList.add(fileName);
            if (StrUtil.equalsIgnoreCase("true", delete)) {
                sftp.delFile(remotePath + "/" + fileName);
            }
        }
        // sftp.recursiveDownloadFolder(, FileUtil.file("d:/test/download"));
        IoUtil.close(sftp);
        return downloadedList;
    }

    /**
     * ftp下载
     *
     * @param config
     * @return java.util.List<java.lang.String>
     */
    public static List<String> ftpDownload(FtpConfig config) throws IOException {
        Ftp ftp = new Ftp(config, FtpMode.Active);
        ftp.lsFiles(remotePath);
        List<String> fileNames = ftp.ls(remotePath);
        if (!"*".equals(filePrefix)) {
            //根据filePrefix 前缀过滤
            fileNames = fileNames.stream().filter(fileName -> fileName.startsWith(filePrefix)).collect(Collectors.toList());
        }
        if (!"*".equals(fileExtension)) {
            //根据fileExtension 后缀过滤
            fileNames = fileNames.stream().filter(fileName -> fileName.endsWith(fileExtension)).collect(Collectors.toList());
        }
        //避免重复下载（远端服务器文件未及时删除，会重复下载），先查看已经下载过的文件
        File file = FileUtil.touch(countFilePath, "downloadedFileNames" + ".ini");
        Ini ini = new Ini(file);
        Set<String> downloadedFileNames = ini.get("downloadedFileNames").keySet();
        //筛选出没有下载的文件名
        fileNames = fileNames.stream().filter(fileName -> !downloadedFileNames.contains(fileName)).collect(Collectors.toList());
        ArrayList<String> downloadedList = new ArrayList<>();
        for (String fileName : fileNames) {
            //先下载到备份补录
            ftp.download(remotePath + "/" + fileName, FileUtil.file(localBackPath, fileName));
            //再从备份复制到本地目录
            FileUtil.copy(FileUtil.file(localBackPath, fileName), FileUtil.file(localPath, fileName), true);
            downloadedList.add(fileName);
            if (StrUtil.equalsIgnoreCase("true", delete)) {
                ftp.delFile(remotePath + "/" + fileName);
            }
        }
        IoUtil.close(ftp);
        return downloadedList;
    }

}
